package com.xbongbong.saas.analytical.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.elasticsearch.model.PaasFormDataEsModel;
import com.xbongbong.paas.elasticsearch.util.EsUtil;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.FlowStatusEnum;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.help.team.TeamUserHelp;
import com.xbongbong.paas.pojo.dto.ValidateDataDTO;
import com.xbongbong.paas.pojo.vo.FormDataRepeatVO;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.pro.constant.ElasticConstant;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.form.pojo.dto.ContactDataRepeatDTO;
import com.xbongbong.pro.formdata.pojo.SaasNeedRedundantAttrPojo;
import com.xbongbong.saas.analytical.SaasValidateAnalyticalService;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.ErrorMessageConstant;
import com.xbongbong.saas.constant.ParameterConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.ext.CustomerEntityExt;
import com.xbongbong.saas.enums.PhoneRepeatRuleEnum;
import com.xbongbong.saas.enums.RedundantTemplateTypeEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.ContactEnum;
import com.xbongbong.saas.help.SaasDataInitHelp;
import com.xbongbong.saas.help.SaveFormatHelp;
import com.xbongbong.saas.model.ContactUserModel;
import com.xbongbong.saas.model.CustomerModel;
import com.xbongbong.saas.model.IndexTypeModel;
import com.xbongbong.saas.toolbox.help.FastJsonHelper;
import org.apache.commons.collections4.CollectionUtils;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
import static org.elasticsearch.index.query.QueryBuilders.termQuery;

/**
 * @author 吴峰
 * @date 2021/07/15 14:28
 */
@Service("ContactAnalyticalServiceImpl")
public class ContactValidateAnalyticalServiceImpl implements SaasValidateAnalyticalService {

    private static final Logger LOG = LoggerFactory.getLogger(ContactValidateAnalyticalServiceImpl.class);

    @Resource
    private CustomerModel customerModel;
    @Resource
    private ContactUserModel contactUserModel;
    @Resource
    private PaasFormDataEsModel paasFormDataEsModel;
    @Resource
    private TeamUserHelp teamUserHelp;
    @Resource
    private IndexTypeModel indexTypeModel;

    @Override
    public List<Integer> type() {
        return Arrays.asList(XbbRefTypeEnum.CONTACT.getCode());
    }
    @Override
    public void analyticalData(ValidateDataDTO validateDataDTO) throws XbbException {
        beforeSave(validateDataDTO);
        teamUserHelp.beforeVerifyUserTeam(validateDataDTO);
    }

    public void beforeSave(ValidateDataDTO validateDataDTO) throws XbbException{
        String corpid = validateDataDTO.getCorpid();
        JSONObject data = validateDataDTO.getData();
        SaasDataInitHelp.antDataSet(data, ContactEnum.IS_MAIN.getAttr(), BasicConstant.ZERO);
        Map<String, FieldAttrEntity> explainMap = validateDataDTO.getExplainMap();
        Long id = validateDataDTO.getDataId();
        FieldAttrEntity fieldAttrEntity = new FieldAttrEntity();
        FieldAttrEntity customerNameField = explainMap.getOrDefault(ContactEnum.CUSTOMER_NAME.getAttr(), fieldAttrEntity);
        // 格式化关联客户
        SaveFormatHelp.formatLinkBusiness4Save(data, ContactEnum.CUSTOMER_NAME.getAttr(), ContactEnum.CUSTOMER_NAME_LINK_TEXT.getAttr(), ContactEnum.CUSTOMER_NAME.getFieldType());
        // 是否来自关联新建
        SaasNeedRedundantAttrPojo saasNeedRedundantAttrPojo = validateDataDTO.getSaasNeedRedundantAttrPoJo();
        Integer isRelationItem = 0;
        if (!Objects.isNull(saasNeedRedundantAttrPojo)) {
            isRelationItem = saasNeedRedundantAttrPojo.getIsRelationItem();
        }
        Long customerId = FastJsonHelper.getLongFromFormData(data, ContactEnum.CUSTOMER_NAME.getAttr());
        // 校验关联客户是否存在，客户可以为非必填
        if (!Objects.equals(isRelationItem,1) && Objects.equals(BasicConstant.ONE, customerNameField.getRequired())) {
            if (customerId == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100028.getCode(), ErrorMessageConstant.PLEASE_SELECT, Objects.toString(customerNameField.getAttrName(), ""));
            }
            CustomerEntityExt customerEntityExt = customerModel.getByKey(customerId, corpid);
            if (customerEntityExt == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100028.getCode(), ErrorMessageConstant.ATTR_NOT_EXIST, Objects.toString(customerNameField.getAttrName(), ""));
            }
            //bug:17151 客户只有1个联系人时，联系人未默认为客户的主联系人
            //List<ContactUserEntity> contactUserList = contactUserModel.getListByCustomerId(corpid, customerId);
            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put(ParameterConstant.CORPID, corpid);
            param.put(ParameterConstant.FLOW_STATUS_IN, FlowStatusEnum.getStatisticType());
            param.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
            IndexTypeEnum indexTypeEnum = indexTypeModel.getByCode(corpid, XbbRefTypeEnum.CONTACT.getCode());
            List<PaasFormDataEntityExt> paasFormDataEntityExts =
                    paasFormDataEsModel.selectByOneCondition(RedundantTemplateTypeEnum.CONTACT.getCode(), ContactEnum.CUSTOMER_NAME.getAttr(), customerId.toString(), param,indexTypeEnum);

            if (Objects.equals(data.get(ContactEnum.IS_MAIN.getAttr()),0)){
                if (CollectionUtils.isEmpty(paasFormDataEntityExts)) {
                    data.put(ContactEnum.IS_MAIN.getAttr(), BasicConstant.ONE);
                }
            }

            //编辑不走更新主联系人的逻辑,并兼容isNew为空的场景
            if (Objects.isNull(validateDataDTO.getIsNew()) || validateDataDTO.getIsNew()) {
                // 若存在主联系人，则需要将当前联系置为非主联系人
                if(CollectionUtils.isNotEmpty(paasFormDataEntityExts)){
                    for(int i=0; i<paasFormDataEntityExts.size(); i++){
                        PaasFormDataEntityExt paasFormDataEntityExt = paasFormDataEntityExts.get(i);
                        if(Objects.equals(paasFormDataEntityExt.getData().get(ContactEnum.IS_MAIN.getAttr()),1)){
                            data.put(ContactEnum.IS_MAIN.getAttr(), BasicConstant.ZERO);
                            break;
                        }
                    }
                }
            }


        }
        // 生日
        SaveFormatHelp.formatBirthday4Save(data, ContactEnum.BIRTHDAY.getAttr(), ContactEnum.BIRTHDAY_FLAG.getAttr(), ContactEnum.BIRTHDAY_MMDD.getAttr());
        // 产品凤娇说取消单个客户判重和全局判重规则 2019/05/18
        // 获取联系人电话字段的电话判重规则
        FieldAttrEntity phoneField = explainMap.getOrDefault(ContactEnum.PHONE.getAttr(), fieldAttrEntity);
        Integer phoneRepeatRule = phoneField.getNoRepeat();
        JSONArray phoneJsonArray = FastJsonHelper.getJsonArrFromFormData(data, ContactEnum.PHONE.getAttr());

        List<String> contactPhoneList = new ArrayList<>();
        if (Objects.equals(isRelationItem,1) && saasNeedRedundantAttrPojo != null) {
            contactPhoneList = saasNeedRedundantAttrPojo.getContactPhoneList();
        }
        if (phoneJsonArray != null) {
            ContactDataRepeatDTO contactDataRepeatDTO = new ContactDataRepeatDTO();
            BeanUtil.copyProperties(validateDataDTO, contactDataRepeatDTO);
            contactDataRepeatDTO.setAttr(ContactEnum.PHONE.getAttr());
            contactDataRepeatDTO.setSubAttr(StringConstant.PHONE_TEL_ATTR);
            contactDataRepeatDTO.setContactId(id);
            contactDataRepeatDTO.setCustomerId(customerId);
            contactDataRepeatDTO.setPhoneRepeatRule(phoneRepeatRule);
            for (Object object : phoneJsonArray) {
                contactDataRepeatDTO.setContactPhoneList(contactPhoneList);
                JSONObject phoneJsonObject = (JSONObject) object;
                String tel = phoneJsonObject.getString(StringConstant.PHONE_TEL_ATTR);
                contactDataRepeatDTO.setTel(tel);
                boolean flag = contactRepeat(contactDataRepeatDTO);
                contactPhoneList.add(tel);
                if (flag) {
                    String msg = String.format(I18nMessageUtil.getMessage(ErrorMessageConstant.PHONE_NUMBER_ALREADY_EXIST), Objects.toString(phoneField.getAttrName(), ""), tel);
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100034, msg);
                }
            }
        }
        validateDataDTO.setData(data);
    }

    public boolean contactRepeat(ContactDataRepeatDTO contactDataRepeatDTO) throws XbbException {
        boolean flag = false;
        Integer phoneRepeatRule = contactDataRepeatDTO.getPhoneRepeatRule();
        String tel = contactDataRepeatDTO.getTel();
        boolean openFlag = Objects.equals(phoneRepeatRule, PhoneRepeatRuleEnum.NOT_OPEN.getCode()) || Objects.equals(null, tel);
        if (openFlag) {
            return false;
        }
        FormDataRepeatVO formDataRepeatVO;
        try {
            boolean ruleFlag;
            ruleFlag = Objects.equals(phoneRepeatRule, PhoneRepeatRuleEnum.GLOBAL_OPEN.getCode()) || Objects.equals(phoneRepeatRule, PhoneRepeatRuleEnum.SINGLE_OPEN.getCode());
            if (ruleFlag) {
                List<String> contactPhoneList = contactDataRepeatDTO.getContactPhoneList();
                for (String contactPhone : contactPhoneList) {
                    if (Objects.equals(tel, contactPhone)) {
                        return true;
                    }
                }
                Long contactId = contactDataRepeatDTO.getContactId();
                String phoneAttr = contactDataRepeatDTO.getAttr();
                String phoneSubAttr = contactDataRepeatDTO.getSubAttr();
                String customerId = Objects.toString(contactDataRepeatDTO.getCustomerId(), "0");
                SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
                BoolQueryBuilder boolQueryBuilder = boolQuery();
                EsUtil.getTermQuery(boolQueryBuilder, contactDataRepeatDTO, true);
                StringBuilder queryPhoneAttr = new StringBuilder(StringConstant.JSON_DATA).append(StringConstant.POINT).append(phoneAttr);
                if (StringUtil.isNotEmpty(phoneSubAttr)) {
                    queryPhoneAttr.append(StringConstant.POINT).append(phoneSubAttr);
                }
                queryPhoneAttr.append(StringConstant.POINT).append(StringConstant.KEY_WORD);
                boolQueryBuilder.filter(termQuery(queryPhoneAttr.toString(), tel));
                if (Objects.equals(phoneRepeatRule, PhoneRepeatRuleEnum.SINGLE_OPEN.getCode())) {
                    StringBuilder customerAttrBuilder = new StringBuilder(StringConstant.JSON_DATA).append(StringConstant.POINT).append(ContactEnum.CUSTOMER_NAME.getAttr()).append(StringConstant.POINT).append(StringConstant.KEY_WORD);
                    boolQueryBuilder.filter(termQuery(customerAttrBuilder.toString(), customerId));
                }
                IndexTypeEnum indexTypeEnum = IndexTypeEnum.IDX_SAAS_CONTACT;
                boolQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD,indexTypeEnum.getType()));
                SearchRequest searchRequest = new SearchRequest(indexTypeEnum.getIndex());
                //TODO 没找到page相关的代码，默认查询20条 2019年6月27日11:08:03
                PageRequest pageRequest = EsUtil.setPage(sourceBuilder, 1, 10);
                sourceBuilder.query(boolQueryBuilder);
                searchRequest.source(sourceBuilder);
                formDataRepeatVO = paasFormDataEsModel.repeat(pageRequest,searchRequest);
                List<PaasFormDataEntityExt> paasFormDataEsEntityList = formDataRepeatVO.getFormDataList();
                Long dataId;
                for (PaasFormDataEntityExt paasFormDataEsEntity : paasFormDataEsEntityList) {
                    dataId = paasFormDataEsEntity.getDataId();
                    if (!Objects.equals(dataId, contactId)) {
                        flag = true;
                        break;
                    }
                }
            }
        } catch (Exception e) {
            LOG.error("contact.repeat查询数据重复出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return flag;
    }

}
